home *** CD-ROM | disk | FTP | other *** search
/ Screensavers 98 / Screensavers 98.iso / scr / pyro / firemain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-28  |  42.5 KB  |  1,133 lines

  1. // *** Fire work Demostration Screen Saver Program ***
  2. // ***** Written by Steven De Toni Febyary 1996 ******
  3. // ***************************************************
  4.  
  5. #include <windows.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9.  
  10. // ***** Include object information *****
  11. #include "config.h"     // Configuration file define constants
  12. #include "ctl3d.h"      // Fancey look to dialog boxes in Win3.1.
  13. #include "fclasses.h"
  14. #include "fix.h"
  15.  
  16.  
  17. // Program varibales !
  18. const  char*      pSzProgName = "Fire Work Screen Saver"; // Program name.
  19. const  int        StrSize     = 256;                  // String size for string processing.
  20. static HINSTANCE  HInst;                              // Handle to main window of application.
  21.  
  22. // *** Prototypes ***
  23. long FAR PASCAL _export    WndProc              (HWND hWnd, WORD message, WORD wParam, LONG lParam);
  24. BOOL FAR PASCAL _export    ConfigDialog         (HWND hDlg, WORD message, WORD wParam, LONG lParam);
  25. BOOL FAR PASCAL _export    SetPasswordDialog    (HWND hDlg, WORD message, WORD wParam, LONG lParam);
  26. BOOL FAR PASCAL _export    GetUserPDialog       (HWND hDlg, WORD message, WORD wParam, LONG lParam);
  27. int UpdateField (HWND hDlg, int cntlID, int direction, int heightLimit, int lowLimit);
  28.  
  29. // Spinner and field entry limits in configuration dialog.
  30. const int ObjRocketMax   = 9000,  ObjRocketMin   = 0;
  31. const int ObjFlowerMax   = 9000,  ObjFlowerMin   = 0;
  32. const int ObjFlareMax    = 9000,  ObjFlareMin    = 1;
  33. const int ObjTrailerMax  = 50,    ObjTrailerMin  = 1;
  34. const int ObjLifeMax     = 2000,  ObjLifeMin     = 10;
  35. const int ObjPicSizeMax  = 4,     ObjPicSizeMin  = 1;
  36.  
  37. const int PicFreqMax     = 10,    PicFreqMin     = 1;
  38. const int PicAngleMax    = 20,    PicAngleMin    = -20;
  39. const int FrameRate      = 0;
  40.  
  41. // Default INI settings.
  42. const char* Section        = "Configuration";
  43. const char* DefIniSettings = "1 50 10 50 1 50 10 100 1 ~ 0";
  44.  
  45. // Timer ID constant.
  46. const int TIMERMAIN   = 10;  // Timer ID within function.
  47. const int TIMERABOUT  = 11;
  48. const int TIMERCONFIG = 12;
  49.  
  50. // Time limit variables for entering password.
  51. const  long PASSWORDCYCLIMIT = 3000; // Timit limit to enter password before dialod is removed.
  52. static long CurrentCycle     = 0;
  53. static HWND HPassDialog      = NULL; // Varible used to commincate with
  54.                                      // Password dialog box, and close it
  55.                                      // after a certain time. If variable is
  56.                                      // not null, then password dialog box is
  57.                                      // open.
  58.  
  59.  
  60. // Current system screen size.
  61. int MAXX, MAXY;
  62.  
  63. // Configuration variables for screen saver.
  64. // These variables are stored in the INI file (win.ini)
  65. static int    RocketNum;
  66. static int    RocketFlareNum;
  67. static int    RocketTrailLen;
  68. static int    RocketLifeCount;
  69.  
  70. static int    FlowerNum;
  71. static int    FlowerFlareNum;
  72. static int    FlowerTrailLen;
  73. static int    FlowerLifeCount;    
  74.  
  75. extern int    PixelSize;            // Pixel size of objects, definied in class definition file.
  76.  
  77. static char   Password   [StrSize/5];
  78. static int    UsePassword;
  79.  
  80.  
  81. // ***************************************************************************************
  82. // Program Entry, and exit.
  83. // ***************************************************************************************
  84. int PASCAL WinMain  (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
  85. {
  86.     HWND            hwnd;
  87.     MSG             msg;
  88.     WNDCLASS        wndclass;
  89.     char            paramBuff[StrSize];
  90.  
  91.     HInst = hInstance;                                  // Assign program instance
  92.     randomize();
  93.  
  94.     if (!hPrevInstance)
  95.     {
  96.         wndclass.style                = CS_BYTEALIGNWINDOW | CS_HREDRAW | CS_VREDRAW;
  97.         wndclass.lpfnWndProc          = (WNDPROC) WndProc;
  98.         wndclass.cbClsExtra           = 0;
  99.         wndclass.hInstance            = HInst;
  100.         wndclass.hIcon                = NULL;
  101.         wndclass.hCursor              = LoadCursor (HInst, MAKEINTRESOURCE(BLANKCURSOR));
  102.         wndclass.hbrBackground        = GetStockObject (BLACK_BRUSH);
  103.         wndclass.lpszMenuName         = NULL;
  104.         wndclass.lpszClassName        = pSzProgName;
  105.         
  106.         RegisterClass (&wndclass);      
  107.     }
  108.     else
  109.         return 0;   // Don't more than one instance of the screen saver
  110.  
  111.     MAXX  = GetSystemMetrics(SM_CXSCREEN);
  112.     MAXY  = GetSystemMetrics(SM_CYSCREEN);
  113.  
  114.     // Check parameter string for configuration command /c
  115.     lstrcpy (paramBuff, lpszCmdParam);
  116.     strupr (paramBuff);
  117.     if (strstr (paramBuff, "/C") != NULL)
  118.     {       
  119.         // Setup the control 3D sub-classing DLL.
  120.         Ctl3dRegister(HInst);
  121.         Ctl3dAutoSubclass(HInst);
  122.  
  123.         // Test Configuration Dialog.
  124.         static FARPROC fpfnConfigDialog;
  125.         fpfnConfigDialog = MakeProcInstance ((FARPROC)ConfigDialog, HInst);
  126.         DialogBox (HInst, MAKEINTRESOURCE(IDD_CONFIGDIALOG), NULL, (DLGPROC) fpfnConfigDialog);
  127.         FreeProcInstance (fpfnConfigDialog);
  128.  
  129.         // Free up usage count of 3D DLL.
  130.         Ctl3dUnregister(HInst);
  131.         return 0;
  132.     }
  133.  
  134.     // Create Screen Saver window.
  135.     hwnd  = CreateWindowEx (WS_EX_TOPMOST,
  136.                          pSzProgName,                   // Window class name
  137.                          "",                            // Window caption
  138.                          WS_POPUP,                      // Window style
  139.                          0,                             // inital X position
  140.                          0,                             // inital y position 
  141.                          MAXX,                          // inital X size
  142.                          MAXY,                          // intial y size
  143.                          NULL,                          // parent window handle
  144.                          NULL,                          // window menu handle
  145.                          HInst,                         // program instance handle
  146.                          NULL);                         // creation parameters
  147.  
  148.  
  149.     // Setup Screen saver timer.
  150.     SetTimer(hwnd, TIMERMAIN, FrameRate, (TIMERPROC) WndProc);
  151.  
  152.     // Go into screen saver mode. 
  153.     ShowWindow (hwnd, nCmdShow);
  154.     UpdateWindow (hwnd);
  155.  
  156.     // Process screen saver messages...
  157.     while (GetMessage (&msg, NULL, 0, 0))
  158.     {
  159.         
  160.         TranslateMessage (&msg);
  161.         DispatchMessage  (&msg);
  162.     }
  163.  
  164.     return msg.wParam;
  165. }
  166.  
  167. // Pic one of the primary colours
  168. COLORREF PicColour (void)
  169. {
  170.     // select primary colour
  171.     switch (random(7))
  172.     {
  173.         case 0:
  174.              return RGB (255, 0, 0);
  175.  
  176.         case 1:
  177.              return RGB (0, 255, 0);
  178.  
  179.         case 2:
  180.              return RGB (0, 0, 255);
  181.  
  182.         case 3:
  183.              return RGB (255, 255, 0);
  184.  
  185.         case 4:
  186.              return RGB (0, 255, 255);
  187.  
  188.         case 5:
  189.              return RGB (255, 0, 255);
  190.  
  191.         case 6:
  192.         default:
  193.              return RGB (255, 255, 255);
  194.     }
  195. }
  196.  
  197.  
  198. // ***************************************************************************
  199. // *** Get User Password Dialog Box. Open up the dialog box to recieve the
  200. // *** user's password.
  201. // ***************************************************************************
  202. BOOL FAR PASCAL _export GetUserPDialog (HWND hDlg, WORD message, WORD wParam, LONG lParam)
  203. {
  204.     switch (message)
  205.     {
  206.         case WM_INITDIALOG:
  207.              HPassDialog  = hDlg;
  208.              CurrentCycle = 0;
  209.              SetActiveWindow (GetDlgItem(hDlg, IDC_GETPASSWORD));
  210.              return TRUE;
  211.  
  212.         case WM_CHAR:
  213.              MessageBeep (-1);
  214.              break;
  215.  
  216.         case WM_KEYDOWN:
  217.         case WM_SYSKEYDOWN:
  218.              return TRUE;
  219.  
  220.         case WM_COMMAND:    // A user has selected a control command
  221.             switch (LOWORD (wParam))
  222.             {
  223.                 case IDC_CANCEL:
  224.                     EndDialog (hDlg, FALSE);
  225.                     HPassDialog = NULL;
  226.                     return TRUE;
  227.                     
  228.                 case IDC_OK:
  229.                      char testPass[StrSize/5];
  230.  
  231.                      GetDlgItemText(hDlg, IDC_GETPASSWORD, testPass, StrSize/5);
  232.                      if (strcmp (Password, testPass) != 0)
  233.                      {
  234.                         MessageBeep(MB_ICONINFORMATION);
  235.                         SetWindowText (hDlg,"Password Incorrect. Retry Entry...");
  236.                         SetActiveWindow (GetDlgItem(hDlg, IDC_GETPASSWORD));
  237.                         break;
  238.                      }
  239.  
  240.                      // If all checks pass ... exit!
  241.                      EndDialog (hDlg, TRUE);
  242.                      HPassDialog = NULL;
  243.                      return TRUE;
  244.  
  245.                 default:
  246.                     break;
  247.             }     
  248.             break;
  249.  
  250.         case WM_CLOSE:
  251.             EndDialog (hDlg, 0);
  252.             HPassDialog = NULL;
  253.             return TRUE;
  254.     }
  255.               
  256.     return FALSE;
  257. }
  258.  
  259.  
  260. // ***************************************************************************
  261. // *** Set Password Dialog Box.
  262. // *** Get user's password from within the configuration dialog box.
  263. // ***************************************************************************
  264. BOOL FAR PASCAL _export SetPasswordDialog (HWND hDlg, WORD message, WORD wParam, LONG lParam)
  265. {
  266.     switch (message)
  267.     {
  268.         case WM_COMMAND:    // A user has selected a control command
  269.             switch (LOWORD (wParam))
  270.             {
  271.                 case IDC_SETPASSWORD:
  272.                      char newPass[StrSize/5];
  273.                      char testPass[StrSize/5];
  274.  
  275.                      GetDlgItemText(hDlg, IDC_NEWPASSWORD, newPass, StrSize/5);
  276.                      if (strlen (newPass) <= 0)
  277.                      {
  278.                         MessageBox (hDlg, "Please Enter A Password First", "*** Entry Error ***",
  279.                                     MB_OK | MB_ICONINFORMATION);
  280.                         break;
  281.                      }
  282.  
  283.                      GetDlgItemText(hDlg, IDC_RETYPEDPASSWORD, testPass, StrSize/5);
  284.                      if (strcmp (newPass, testPass) != 0)
  285.                      {
  286.                         MessageBox (hDlg, "New And Retyped Password Differ", "*** Check Error ***",
  287.                                     MB_OK | MB_ICONINFORMATION);
  288.                         break;
  289.                      }
  290.  
  291.                      // If all checks pass ... then use it !
  292.                      UsePassword = 1;
  293.                      strcpy (Password, testPass);
  294.                      EndDialog (hDlg, 1);
  295.                      break;
  296.  
  297.                 case IDC_CANCELPASSWORD:
  298.                        EndDialog (hDlg, 0);
  299.                      break;
  300.  
  301.                 default:
  302.                     break;
  303.             }     
  304.             break;
  305.  
  306.         case WM_CLOSE:
  307.             EndDialog (hDlg, 0);
  308.             break;
  309.     }
  310.               
  311.     return FALSE;
  312. }
  313.  
  314.  
  315. // ***************************************************************************
  316. // *** About Dialog Box.
  317. // *** Get user's password from within the configuration dialog box.
  318. // ***************************************************************************
  319. BOOL FAR PASCAL _export AboutDialog (HWND hDlg, WORD message, WORD wParam, LONG lParam)
  320. {
  321.     const int flareNum    = 150;
  322.     static Flare*  flares = NULL;
  323.  
  324.     static HDC     virtHdc;
  325.     static HRGN    hNewClipRegion;
  326.     static RECT    clientRect;
  327.     static HBITMAP hDrawBitmap, hOldBitmap;
  328.     static HDC     hdc;
  329.  
  330.     // Colour picking variables.
  331.     const  int      cycleLimit = 100;
  332.     static COLORREF currentCol;
  333.     static int      cycle;
  334.      
  335.     switch (message)
  336.     {
  337.         case WM_INITDIALOG:
  338.  
  339.              // implement timer.
  340.              flares = NULL;
  341.              flares = new Flare[flareNum];
  342.  
  343.              if (flares == NULL)
  344.              {
  345.                 MessageBox (hDlg, "Out Of Memory", "Memory Problems",
  346.                             MB_OK | MB_ICONINFORMATION);
  347.                 PostMessage (hDlg, WM_CLOSE, 0, 0L);
  348.                 break;     // memory allocate error
  349.              }
  350.  
  351.              // set colour cycling
  352.              currentCol = PicColour ();
  353.              cycle      = cycleLimit;
  354.  
  355.              hdc = GetDC (GetDlgItem (hDlg, IDC_MINIWORK));
  356.              // Set map mode and get size of client area.
  357.              SetMapMode (hdc, MM_TEXT);
  358.              GetClientRect(GetDlgItem (hDlg, IDC_MINIWORK), &clientRect);
  359.              clientRect.right-= 2; clientRect.bottom-= 2;
  360.  
  361.              virtHdc     = CreateCompatibleDC      (hdc);
  362.              hDrawBitmap = CreateCompatibleBitmap  (hdc, clientRect.right, clientRect.bottom);
  363.              hOldBitmap  = SelectObject (virtHdc, hDrawBitmap);
  364.              SetMapMode    (virtHdc, MM_TEXT);
  365.  
  366.              // Delete background.
  367.              FillRect(virtHdc, &clientRect, GetStockObject(BLACK_BRUSH));
  368.              hNewClipRegion = CreateRectRgn(clientRect.left, clientRect.top,
  369.                                             clientRect.right, clientRect.bottom);
  370.              SelectClipRgn(virtHdc, hNewClipRegion);
  371.  
  372.              SetTimer(hDlg, TIMERABOUT, FrameRate, (TIMERPROC) AboutDialog);
  373.              break;
  374.  
  375.         case WM_TIMER:
  376.              if (cycle < 0)
  377.              {
  378.                 // reset colour cycling
  379.                 currentCol = PicColour ();
  380.                 cycle      = cycleLimit;
  381.              }
  382.              else
  383.                  cycle--;
  384.  
  385.              for (int count = 0; count < flareNum; count++)
  386.              {
  387.                  if (flares[count].move(virtHdc) == FALSE)
  388.                  {
  389.                      flares[count].init (clientRect.right >> 1, clientRect.bottom >> 1,
  390.                                          ((random (40)-20) * Fixed) >> 2, ((random (40)-20) * Fixed) >> 2,
  391.                                          random(50),
  392.                                          clientRect.bottom-2, random(10)+5,
  393.                                          currentCol);
  394.                  }
  395.              }
  396.  
  397.              hdc = GetDC (GetDlgItem (hDlg, IDC_MINIWORK));
  398.              // Blast virtual screen onto real screen.
  399.              BitBlt (hdc,     1, 1, clientRect.right, clientRect.bottom,
  400.                      virtHdc, 0, 0,
  401.                      SRCCOPY);
  402.              ReleaseDC (GetDlgItem (hDlg, IDC_MINIWORK), hdc);
  403.              break;
  404.  
  405.         case WM_COMMAND:    // A user has selected a control command
  406.             switch (LOWORD (wParam))
  407.             {
  408.                 case IDC_LEAVE:
  409.                      PostMessage (hDlg, WM_CLOSE, 0, 0L);
  410.             }     
  411.             break;
  412.  
  413.         case WM_CLOSE:
  414.             KillTimer(hDlg, TIMERABOUT);
  415.             // Free objects.
  416.             DeleteObject (hNewClipRegion);
  417.             DeleteObject (SelectObject (virtHdc, hOldBitmap));
  418.             DeleteDC     (virtHdc);
  419.             delete flares;
  420.             EndDialog (hDlg, 0);
  421.             break;
  422.     }
  423.               
  424.     return FALSE;
  425. }
  426.  
  427.  
  428. // **********************************************************************************
  429. // Updated process spinner controls (aka: scroll bars).
  430. //
  431. // hDlg        = handle to dialog box
  432. // cntlID      = ID number of text field
  433. // direction   = 1, for up, -1 for down, 0 = dont increment/decrement
  434. // heightLimit = max number (inclusive).
  435. // lowlimit    = min number (inclusive).
  436. //
  437. // Returns integer value of field.
  438. int UpdateField (HWND hDlg, int cntlID, int direction, int heightLimit, int lowLimit)
  439. {
  440.     char buffer[StrSize];
  441.     int  number;
  442.  
  443.     // Get text
  444.     GetDlgItemText(hDlg, cntlID, buffer, StrSize);
  445.  
  446.     // convert string.
  447.     number = atoi (buffer);
  448.     
  449.     // Check field constraints.
  450.     if ((direction >= 1) && (number < heightLimit))       // Increment.
  451.        number++;
  452.     else
  453.         if ((direction <= -1) && (number > lowLimit))     // Decrement.
  454.            number--;
  455.  
  456.     // Implement simple limit, and error check from conversion from text.
  457.     if (number > heightLimit)
  458.        number = heightLimit;
  459.     else if (number < lowLimit)
  460.             number = lowLimit;
  461.  
  462.     // Redisplay number into field
  463.     sprintf (buffer, "%d", number);
  464.     SetDlgItemText(hDlg, cntlID, buffer);
  465.  
  466.     // return number value.
  467.     return number;
  468.  
  469.  
  470. // **********************************************************************************
  471. // Function to process scroll bar messages and update spinner fields.
  472. //
  473. // hDlg   = handle to dialog box
  474. // wParam = Scroll bar message
  475. // lParam = control dialog handle
  476. // 
  477. // returns TRUE if spinner message was processed,
  478. //         FALSE if it wasn't. 
  479. BOOL ProcessSpinners (HWND hDlg, WORD wParam, LONG lParam)
  480. {
  481.     switch (wParam) // Find what type of action.
  482.     {
  483.          case SB_LINEDOWN:
  484.             switch (GetDlgCtrlID(HIWORD(lParam))) /* handle of the control */
  485.             {
  486.                 // Sky rocket number
  487.                 case IDC_ROCKNUMSPIN:
  488.                     UpdateField (hDlg, IDC_ROCKNUMEDIT, -1, ObjRocketMax, ObjRocketMin);
  489.                     return TRUE;
  490.  
  491.                 // Rocket flare number
  492.                 case IDC_ROCKFNUMSPIN:
  493.                     UpdateField (hDlg, IDC_ROCKFNUMEDIT, -1, ObjFlareMax, ObjFlareMin);
  494.                     return TRUE;
  495.  
  496.                 // Rocket Trail Length
  497.                 case IDC_ROCKTNUMSPIN:
  498.                     UpdateField (hDlg, IDC_ROCKTNUMEDIT, -1, ObjTrailerMax, ObjTrailerMin);
  499.                     return TRUE;
  500.  
  501.                 // Rocket Life Counter
  502.                 case IDC_ROCKLNUMSPIN:
  503.                     UpdateField (hDlg, IDC_ROCKLNUMEDIT, -1, ObjLifeMax, ObjLifeMin);
  504.                     return TRUE;
  505.  
  506.                 // *****************************************************************************
  507.  
  508.                 // Flower pot number
  509.                 case IDC_FLOWERNUMSPIN:
  510.                     UpdateField (hDlg, IDC_FLOWERNUMEDIT, -1, ObjFlowerMax, ObjFlowerMin);
  511.                     return TRUE;
  512.  
  513.                 // Rocket flare number
  514.                 case IDC_FLOWERFNUMSPIN:
  515.                     UpdateField (hDlg, IDC_FLOWERFNUMEDIT, -1, ObjFlareMax, ObjFlareMin);
  516.                     return TRUE;
  517.  
  518.                 // Rocket Trail Length
  519.                 case IDC_FLOWERTNUMSPIN:
  520.                     UpdateField (hDlg, IDC_FLOWERTNUMEDIT, -1, ObjTrailerMax, ObjTrailerMin);
  521.                     return TRUE;
  522.  
  523.                 // Rocket Life Counter
  524.                 case IDC_FLOWERLNUMSPIN:
  525.                     UpdateField (hDlg, IDC_FLOWERLNUMEDIT, -1, ObjLifeMax, ObjLifeMin);
  526.                     return TRUE;
  527.  
  528.                 // Pixel Size Counter
  529.                 case IDC_PIXELSIZESPIN:
  530.                     UpdateField (hDlg, IDC_PIXELSIZEEDIT, -1, ObjPicSizeMax, ObjPicSizeMin);
  531.                     return TRUE;
  532.  
  533.                 // *****************************************************************************
  534.  
  535.                 // Picture frequency and angle spinners.
  536.                 case IDC_PICFREQSPIN:
  537.                      UpdateField (hDlg, IDC_PICFREQEDIT, -1, PicFreqMax, PicFreqMin);
  538.                      return TRUE;
  539.  
  540.                 case IDC_PICANGLESPIN:
  541.                      UpdateField (hDlg, IDC_PICANGLEEDIT, -1, PicAngleMax, PicAngleMin);
  542.                      return TRUE;
  543.             }
  544.             break;
  545.  
  546.         case SB_LINEUP:
  547.             switch (GetDlgCtrlID(HIWORD(lParam)))  /* handle of the control */
  548.             {
  549.                 // Sky rocket number
  550.                 case IDC_ROCKNUMSPIN:
  551.                     UpdateField (hDlg, IDC_ROCKNUMEDIT, 1, ObjRocketMax, ObjRocketMin);
  552.                     return TRUE;
  553.  
  554.                 // Rocket flare number
  555.                 case IDC_ROCKFNUMSPIN:
  556.                     UpdateField (hDlg, IDC_ROCKFNUMEDIT, 1, ObjFlareMax, ObjFlareMin);
  557.                     return TRUE;
  558.  
  559.                 // Rocket Trail Length
  560.                 case IDC_ROCKTNUMSPIN:
  561.                     UpdateField (hDlg, IDC_ROCKTNUMEDIT, 1, ObjTrailerMax, ObjTrailerMin);
  562.                     return TRUE;
  563.  
  564.                 // Rocket Life Counter
  565.                 case IDC_ROCKLNUMSPIN:
  566.                     UpdateField (hDlg, IDC_ROCKLNUMEDIT, 1, ObjLifeMax, ObjLifeMin);
  567.                     return TRUE;
  568.  
  569.                 // *****************************************************************************
  570.  
  571.                 // Flower pot number
  572.                 case IDC_FLOWERNUMSPIN:
  573.                     UpdateField (hDlg, IDC_FLOWERNUMEDIT, 1, ObjFlowerMax, ObjFlowerMin);
  574.                     return TRUE;
  575.  
  576.                 // Rocket flare number
  577.                 case IDC_FLOWERFNUMSPIN:
  578.                     UpdateField (hDlg, IDC_FLOWERFNUMEDIT, 1, ObjFlareMax, ObjFlareMin);
  579.                     return TRUE;
  580.  
  581.                 // Rocket Trail Length
  582.                 case IDC_FLOWERTNUMSPIN:
  583.                     UpdateField (hDlg, IDC_FLOWERTNUMEDIT, 1, ObjTrailerMax, ObjTrailerMin);
  584.                     return TRUE;
  585.  
  586.                 // Rocket Life Counter
  587.                 case IDC_FLOWERLNUMSPIN:
  588.                     UpdateField (hDlg, IDC_FLOWERLNUMEDIT, 1, ObjLifeMax, ObjLifeMin);
  589.                     return TRUE;
  590.  
  591.                 // Pixel Size Counter
  592.                 case IDC_PIXELSIZESPIN:
  593.                     UpdateField (hDlg, IDC_PIXELSIZEEDIT, 1, ObjPicSizeMax, ObjPicSizeMin);
  594.                     return TRUE;
  595.  
  596.                 // *****************************************************************************
  597.  
  598.                 // Picture frequency and angle spinners.
  599.                 case IDC_PICFREQSPIN:
  600.                      UpdateField (hDlg, IDC_PICFREQEDIT, 1, PicFreqMax, PicFreqMin);
  601.                      return TRUE;
  602.  
  603.                 case IDC_PICANGLESPIN:
  604.                      UpdateField (hDlg, IDC_PICANGLEEDIT, 1, PicAngleMax, PicAngleMin);
  605.                      return TRUE;
  606.             }
  607.             break;
  608.     }
  609.  
  610.     return FALSE;
  611. }
  612.  
  613. // **********************************************************************************
  614. // Function used to retrieve the field values from the configuration dialog box,
  615. // and place them into the INI configuration (global) variables. Used in
  616. // save INI settings.
  617. void GetFieldInfo (HWND hDlg)
  618. {
  619.  
  620.      // Get configuration information.
  621.      RocketNum       = UpdateField (hDlg, IDC_ROCKNUMEDIT,  0, ObjRocketMax,  ObjRocketMin);
  622.      RocketFlareNum  = UpdateField (hDlg, IDC_ROCKFNUMEDIT, 0, ObjFlareMax,   ObjFlareMin);
  623.      RocketTrailLen  = UpdateField (hDlg, IDC_ROCKTNUMEDIT, 0, ObjTrailerMax, ObjTrailerMin);
  624.      RocketLifeCount = UpdateField (hDlg, IDC_ROCKLNUMEDIT, 0, ObjLifeMax,    ObjLifeMin);
  625.  
  626.      FlowerNum       = UpdateField (hDlg, IDC_FLOWERNUMEDIT,  0, ObjFlowerMax,  ObjFlowerMin);
  627.      FlowerFlareNum  = UpdateField (hDlg, IDC_FLOWERFNUMEDIT, 0, ObjFlareMax,   ObjFlareMin);
  628.      FlowerTrailLen  = UpdateField (hDlg, IDC_FLOWERTNUMEDIT, 0, ObjTrailerMax, ObjTrailerMin);
  629.      FlowerLifeCount = UpdateField (hDlg, IDC_FLOWERLNUMEDIT, 0, ObjLifeMax,    ObjLifeMin);
  630.  
  631.      // Pixel Size Counter
  632.      PixelSize       = UpdateField (hDlg, IDC_PIXELSIZEEDIT, 0, ObjPicSizeMax, ObjPicSizeMin);
  633. }
  634.  
  635.  
  636. // mode = 0 to return current bitmap DC
  637. //        1 for intialise variables
  638. //        2 to free variables
  639. HDC LoadBitmap (int mode, BITMAP& bmp, HBITMAP hTitle = 0, HWND hWnd = 0)
  640. {
  641.     static HBITMAP hOldBmp;
  642.     static HDC     hdcSrc = NULL;
  643.  
  644.     switch (mode)
  645.     {
  646.         case 0:
  647.              break;
  648.  
  649.         case 1:
  650.              HDC hdcDest = GetDC(hWnd);
  651.  
  652.              hdcSrc  = CreateCompatibleDC(hdcDest);
  653.              GetObject(hTitle, sizeof(BITMAP), &bmp);
  654.              hOldBmp = SelectObject(hdcSrc, hTitle);
  655.              SetMapMode (hdcSrc, MM_TEXT);
  656.              RealizePalette(hdcSrc);
  657.              ReleaseDC  (hWnd, hdcDest);
  658.              break;
  659.  
  660.         case 2:
  661.              SelectObject (hdcSrc, hOldBmp);
  662.              DeleteDC (hdcSrc);
  663.              hdcSrc = NULL;
  664.              break;
  665.     }
  666.  
  667.     return hdcSrc;
  668. }
  669.  
  670. // mode = 0 to return current bitmap DC
  671. //        1 for intialise variables
  672. //        2 to free variables
  673. HDC CreateVirtualHDC (int mode, HWND hWnd = 0)
  674. {
  675.     static HDC     virtHdc = NULL;
  676.     static HBITMAP hDrawBitmap, hOldBitmap;
  677.  
  678.     switch (mode)
  679.     {
  680.         case 0:
  681.              break;
  682.  
  683.         case 1:
  684.              HDC  hdcDest   = GetDC (hWnd);
  685.              RECT clientRect;
  686.  
  687.              // Set map mode and get size of client area.
  688.              SetMapMode (hdcDest, MM_TEXT);
  689.              GetClientRect(hWnd, &clientRect);
  690.  
  691.              virtHdc     = CreateCompatibleDC      (hdcDest);
  692.              SetMapMode (virtHdc, MM_TEXT);
  693.              hDrawBitmap = CreateCompatibleBitmap  (hdcDest,
  694.                                                     clientRect.right,
  695.                                                     clientRect.bottom);
  696.  
  697.              hOldBitmap  = SelectObject (virtHdc, hDrawBitmap);
  698.              SetMapMode    (virtHdc, MM_TEXT);
  699.  
  700.              FillRect(virtHdc, &clientRect, GetStockObject(BLACK_BRUSH));
  701.              ReleaseDC  (hWnd, hdcDest);
  702.              break;
  703.  
  704.         case 2:
  705.             DeleteObject (SelectObject (virtHdc, hOldBitmap));
  706.             DeleteDC     (virtHdc);
  707.             virtHdc = NULL;
  708.     }
  709.  
  710.     return virtHdc;
  711. }
  712.  
  713. void SinePic (int xPos, int yPos, int freq, unsigned int startAngle,
  714.               BITMAP& bmp, HDC hdcBitmap, HDC hdcDisplay, HDC hdcVirtual)
  715. {
  716.     int  sPos   = startAngle;
  717.     int  yPut;
  718.     long mid    = bmp.bmHeight >> 1;
  719.  
  720.     HBRUSH blkBrush;
  721.     RECT   blankArea;
  722.  
  723.     // erase old picture from virtual memory
  724.     blankArea.left   = xPos;
  725.     blankArea.top    = yPos - (bmp.bmHeight >> 1);
  726.     blankArea.right  = xPos + bmp.bmWidth;
  727.     blankArea.bottom = yPos + bmp.bmHeight + (bmp.bmHeight >> 1);
  728.  
  729.     blkBrush = CreateSolidBrush (GetSysColor(COLOR_BTNFACE));
  730.     // FillRect (hdcDisplay, &blankArea, blkBrush);
  731.     FillRect (hdcVirtual, &blankArea, blkBrush);
  732.     DeleteObject (blkBrush);   
  733.  
  734.     for (int count = bmp.bmWidth + xPos; count > xPos; count--)
  735.     {
  736.         yPut = ((int) (SIN (sPos % NUMOFDEGREES) * mid) >> SHIFT) + yPos;
  737.  
  738.         // Plaster bitmap onto sine wave!
  739.         BitBlt (hdcVirtual, count, yPut, 1, bmp.bmHeight,
  740.                 hdcBitmap,  count-xPos, 0, SRCCOPY);
  741.  
  742.         sPos += freq;
  743.     }
  744.  
  745.     // Blast virtual screen onto real display
  746.     BitBlt (hdcDisplay, blankArea.left, blankArea.top, bmp.bmWidth, (bmp.bmHeight << 1) - 1,
  747.             hdcVirtual, blankArea.left, blankArea.top, SRCCOPY);
  748. }
  749.  
  750.  
  751. // ***************************************************************************
  752. // *** Configuration Dialog Box.
  753. BOOL FAR PASCAL _export ConfigDialog (HWND hDlg, WORD message, WORD wParam, LONG lParam)
  754. {
  755.     // used to read in configuration settings.
  756.     char profileBuff[StrSize * 2];
  757.  
  758.     BOOL   success;
  759.     int    bytesRead;
  760.  
  761.     // ****** Bitmap Sinus variables *****
  762.     static HBITMAP      hTitle = NULL;
  763.     static BITMAP       bmp;
  764.     static unsigned int curAngle;
  765.     static          int freqInc;
  766.     static          int angleInc;
  767.     static          int picPutY;
  768.     static          int picPutX;
  769.  
  770.     switch (message)
  771.     {
  772.         case WM_INITDIALOG:
  773.              // Read in INI settings and display these in fields.
  774.              GetProfileString(pSzProgName, Section,
  775.                               DefIniSettings, profileBuff, StrSize * 2);
  776.              sscanf (profileBuff, "%d %d %d %d %d %d %d %d %d %s %d",
  777.                                   &RocketNum,      &RocketFlareNum,
  778.                                   &RocketTrailLen, &RocketLifeCount,
  779.  
  780.                                   &FlowerNum,      &FlowerFlareNum,
  781.                                   &FlowerTrailLen, &FlowerLifeCount,
  782.                                   &PixelSize,
  783.  
  784.                                   Password, &UsePassword);
  785.  
  786.              // Setup password settings.
  787.              CheckDlgButton(hDlg, IDC_SETPASSWORD, UsePassword);
  788.              EnableWindow(GetDlgItem(hDlg, IDC_LOADPWDIALOG), (BOOL) UsePassword);
  789.  
  790.              // Set Parameters into feilds.
  791.              SetDlgItemInt(hDlg, IDC_ROCKNUMEDIT,    RocketNum,       TRUE);
  792.              SetDlgItemInt(hDlg, IDC_ROCKFNUMEDIT,   RocketFlareNum,  TRUE);
  793.              SetDlgItemInt(hDlg, IDC_ROCKTNUMEDIT,   RocketTrailLen,  TRUE);
  794.              SetDlgItemInt(hDlg, IDC_ROCKLNUMEDIT,   RocketLifeCount, TRUE);
  795.  
  796.              SetDlgItemInt(hDlg, IDC_FLOWERNUMEDIT,  FlowerNum,       TRUE);
  797.              SetDlgItemInt(hDlg, IDC_FLOWERFNUMEDIT, FlowerFlareNum,  TRUE);
  798.              SetDlgItemInt(hDlg, IDC_FLOWERTNUMEDIT, FlowerTrailLen,  TRUE);
  799.              SetDlgItemInt(hDlg, IDC_FLOWERLNUMEDIT, FlowerLifeCount, TRUE);
  800.  
  801.              SetDlgItemInt(hDlg, IDC_PIXELSIZEEDIT,  PixelSize, TRUE);
  802.  
  803.  
  804.              // Setup scrolling bitmap.
  805.              // ***********************
  806.              // Load bitmap from resources.
  807.              
  808.              hTitle = LoadBitmap (HInst, MAKEINTRESOURCE (IDB_TITLE));
  809.  
  810.              // Setup bitmap DC
  811.              LoadBitmap (1, bmp, hTitle, hDlg);
  812.  
  813.              // Setup virtual DC
  814.              CreateVirtualHDC (1, hDlg);
  815.  
  816.              // Set position variables,
  817.              RECT clientRect;
  818.              GetClientRect (hDlg, &clientRect);     // Get size of client area
  819.              picPutY = 40;
  820.              picPutX = (clientRect.right / 2) - (bmp.bmWidth / 2);
  821.  
  822.              // Set incremental variables,
  823.              freqInc  = 2;
  824.              angleInc = 5;
  825.              SetDlgItemInt(hDlg, IDC_PICFREQEDIT,   freqInc, TRUE);
  826.              SetDlgItemInt(hDlg, IDC_PICANGLEEDIT,  angleInc, TRUE);
  827.              
  828.              curAngle = 0;
  829.  
  830.              // Set timer
  831.              SetTimer(hDlg,  TIMERCONFIG, FrameRate, (TIMERPROC) ConfigDialog);
  832.              return TRUE;
  833.  
  834.         // Process Scroll Bitmap 
  835.         case WM_TIMER:
  836.             HDC  dispDC = GetDC (hDlg);
  837.  
  838.             // sinus scroll bitmap onto display DC
  839.             SinePic (picPutX, picPutY,
  840.                      freqInc, curAngle % NUMOFDEGREES, bmp,
  841.                      LoadBitmap (0, bmp),
  842.                      dispDC, CreateVirtualHDC(0)
  843.                     );
  844.             ReleaseDC (hDlg, dispDC);
  845.  
  846.             curAngle+= angleInc;
  847.             break;
  848.  
  849.         // Process spinner (AKA: scroll bars) controls.
  850.         case WM_VSCROLL:
  851.  
  852.             // Update picture sinus scroll increment variables. 
  853.             if (ProcessSpinners (hDlg, wParam, lParam) != FALSE)
  854.             {
  855.                 // Update these variables on every spinner message
  856.                 freqInc  = UpdateField (hDlg, IDC_PICFREQEDIT, 0, PicFreqMax, PicFreqMin);
  857.                 angleInc = UpdateField (hDlg, IDC_PICANGLEEDIT, 0, PicAngleMax, PicAngleMin);
  858.             }
  859.             break;
  860.  
  861.         case WM_COMMAND:    // A user has selected a control command
  862.             switch (LOWORD (wParam))
  863.             {
  864.                 case IDC_SETPASSWORD:
  865.                      if (UsePassword != 0)
  866.                         UsePassword = 0;
  867.                      else
  868.                          UsePassword = 1;
  869.  
  870.                      CheckDlgButton(hDlg, IDC_SETPASSWORD, UsePassword);
  871.                      EnableWindow(GetDlgItem(hDlg, IDC_LOADPWDIALOG), (BOOL) UsePassword);
  872.                      break;
  873.  
  874.                 case IDC_LOADPWDIALOG:
  875.                      // Test Configuration Dialog.
  876.                      static FARPROC fpfnSetPasswordDialog;
  877.                      fpfnSetPasswordDialog = MakeProcInstance ((FARPROC)SetPasswordDialog, HInst); // Place in window constructor
  878.                      DialogBox (HInst, MAKEINTRESOURCE(IDD_NEWPASSWORD), hDlg, (DLGPROC) fpfnSetPasswordDialog);
  879.                      FreeProcInstance (fpfnSetPasswordDialog);
  880.                      break;
  881.  
  882.                 case IDC_SETIT:     // Save settings.
  883.                      // Get user data.
  884.                      GetFieldInfo (hDlg);
  885.  
  886.                      // Write settings to profile string.
  887.                     sprintf (profileBuff, "%d %d %d %d %d %d %d %d %d %s %d",
  888.                                           RocketNum,      RocketFlareNum,
  889.                                           RocketTrailLen, RocketLifeCount,
  890.  
  891.                                           FlowerNum,      FlowerFlareNum,
  892.                                           FlowerTrailLen, FlowerLifeCount,
  893.                                           PixelSize,
  894.  
  895.                                           Password, UsePassword);
  896.  
  897.                      success = WriteProfileString(pSzProgName, Section,
  898.                                                   profileBuff);
  899.                      if (success == FALSE)
  900.                      {
  901.                         MessageBox(hDlg, "Unable to save settings!",
  902.                                          "*** Write Profile String ***",
  903.                                          MB_ICONSTOP | MB_OK | MB_TASKMODAL);
  904.                         break;
  905.                      }
  906.  
  907.                 case IDC_FORGETIT:  // Don't save settings.
  908.                        EndDialog (hDlg, 0);
  909.                      break;
  910.  
  911.                 case IDC_ABOUT:
  912.                      static FARPROC fpfnAboutDialog;
  913.  
  914.                      KillTimer(hDlg, TIMERCONFIG);
  915.                      fpfnAboutDialog = MakeProcInstance ((FARPROC)AboutDialog, HInst); // Place in window constructor
  916.                      // Get current pixel size.
  917.                      PixelSize = UpdateField (hDlg, IDC_PIXELSIZEEDIT, 0, ObjPicSizeMax, ObjPicSizeMin);
  918.                      DialogBox (HInst, MAKEINTRESOURCE(IDD_ABOUT), hDlg, (DLGPROC) fpfnAboutDialog);
  919.                      FreeProcInstance (fpfnAboutDialog);
  920.                      SetTimer(hDlg, TIMERCONFIG, FrameRate, (TIMERPROC) ConfigDialog);
  921.                      break;
  922.  
  923.                 default:
  924.                     break;
  925.             }     
  926.             break;
  927.  
  928.         case WM_CLOSE:
  929.             KillTimer(hDlg, TIMERCONFIG);
  930.             LoadBitmap (2, bmp);
  931.             CreateVirtualHDC (2);
  932.             DeleteObject (hTitle);
  933.  
  934.             EndDialog (hDlg, 0);
  935.             break;
  936.     }
  937.               
  938.     return FALSE;
  939. }
  940.  
  941. // ***************************************************************************************
  942. // ******************************* Screen Saver function *********************************
  943. // **** Message Main dispatcher ! ****
  944. long FAR PASCAL _export WndProc (HWND hWnd, WORD message, WORD wParam, LONG lParam)
  945. {
  946.     // Password checking routines
  947.     const  LONG testPW = 0xffff;    // internal private message to init password entry. 
  948.     static semiphore   = 0;         // Only one password entry can exist, this is incremented
  949.                                     // to indicated such. (i.e. windows sends multiple useless
  950.                                     // messages that required to method to be here).
  951.  
  952.     // Object variables.
  953.     static SkyRocket*    pMyRockets = NULL;
  954.     static FlowerPot*    pMyPots    = NULL;
  955.            char          profileBuff[StrSize * 2];
  956.     static int           count;
  957.  
  958.     // Store last mouse positions, and check if it's changed.
  959.     static POINT   lastMPos;
  960.  
  961.     switch (message)
  962.     {                           
  963.         // Window Constructor                
  964.         case WM_CREATE:
  965.              // Read in INI settings and display these in fields.
  966.              GetProfileString(pSzProgName, Section,
  967.                               DefIniSettings, profileBuff, StrSize * 2);
  968.              sscanf (profileBuff, "%d %d %d %d %d %d %d %d %d %s %d",
  969.                                   &RocketNum,      &RocketFlareNum,
  970.                                   &RocketTrailLen, &RocketLifeCount,
  971.  
  972.                                   &FlowerNum,      &FlowerFlareNum,
  973.                                   &FlowerTrailLen, &FlowerLifeCount,
  974.                                   &PixelSize,
  975.  
  976.                                   Password, &UsePassword);
  977.  
  978.  
  979.              // Allocate memory for objects .... only in local heap though.
  980.              pMyRockets = new SkyRocket[RocketNum];
  981.              pMyPots    = new FlowerPot[FlowerNum];
  982.              
  983.              if ((pMyRockets == NULL) || (pMyPots == NULL))
  984.              {
  985.                  delete pMyRockets, pMyPots;
  986.  
  987.                  MessageBox (hWnd, "Unable to Allocate Memory!", "*** Memory Error ***",
  988.                              MB_OK | MB_TASKMODAL | MB_ICONSTOP);
  989.                  PostQuitMessage (0);
  990.                  return 0;
  991.              }
  992.  
  993.  
  994.              MAXY--;                        // Adjust so that ground is visible on screen.
  995.              for (count = 0; count < RocketNum; count++)
  996.              {
  997.                     pMyRockets[count].init (RocketFlareNum,             // N.O of flares     
  998.                                             MAXX >> 1, MAXY,            // x, y start location
  999.                                             ((random (15)-7) * Fixed), // Horz thrust
  1000.                                             ((random (15)+10) * Fixed),  // Vert thrust
  1001.                                             random(RocketLifeCount),    // Life counter
  1002.                                             MAXY,                       // Ground
  1003.                                             RocketTrailLen,             // Trailer Length
  1004.                                             PicColour ()                // colour
  1005.                                            );
  1006.              }
  1007.  
  1008.              for (count = 0; count < FlowerNum; count++)
  1009.              {
  1010.                     pMyPots[count].init (FlowerFlareNum,                                                 // N.O of flares     
  1011.                                          random(MAXX >> 1) + (MAXX >> 2), MAXY,                          // x, y start location
  1012.                                          PicColour (),  // colour
  1013.                                          random(FlowerLifeCount >> 1) + (FlowerLifeCount >> 1),            // Life counter
  1014.                                          FlowerTrailLen                                                  // Trailer Length
  1015.                                         ); 
  1016.              }
  1017.  
  1018.              // Get current mouse positions
  1019.              GetCursorPos(&lastMPos);
  1020.              ShowCursor (FALSE);
  1021.              break;
  1022.  
  1023.         case WM_TIMER:
  1024.              HDC    hdc = GetDC (hWnd);
  1025.  
  1026.              // ########## Update Sky Rockets ##########
  1027.              for (count = 0; count < RocketNum; count++)
  1028.              {
  1029.                  if (pMyRockets[count].move(hdc) == FALSE)
  1030.                  {
  1031.                      pMyRockets[count].init (RocketFlareNum,                                              // N.O of flares
  1032.                                              MAXX >> 1, MAXY,                                             // x, y start location
  1033.                                              ((random (15)-7) * Fixed),                                  // Horz thrust                   
  1034.                                              ((random (15)+10) * Fixed),                                   // Vert thrust
  1035.                                              random(RocketLifeCount),         // Life counter
  1036.                                              MAXY,                                                        // Ground
  1037.                                              RocketTrailLen,                                              // Trailer Length
  1038.                                              PicColour ()                                                 // colour
  1039.                                             );
  1040.                  }
  1041.              }
  1042.  
  1043.              // ########## Update Flower Pots ##########
  1044.              for (count = 0; count < FlowerNum; count++)
  1045.              {
  1046.                  if (pMyPots[count].move(hdc) == FALSE)
  1047.                  {
  1048.                      pMyPots[count].init (FlowerFlareNum,                                                 // N.O of flares     
  1049.                                           random(MAXX >> 1) + (MAXX >> 2), MAXY,                          // x, y start location
  1050.                                           PicColour (),  // colour
  1051.                                           random(FlowerLifeCount >> 1) + (FlowerLifeCount >> 1),
  1052.                                           FlowerTrailLen                                                  // Trailer Length
  1053.                                          );
  1054.                  }
  1055.              }
  1056.              ReleaseDC (hWnd, hdc);
  1057.  
  1058.              // If to long send password dialog box a close message.
  1059.              if (HPassDialog != NULL)
  1060.              {
  1061.                  CurrentCycle++;
  1062.                  if (CurrentCycle >= PASSWORDCYCLIMIT)
  1063.                  {
  1064.                      PostMessage (HPassDialog, WM_CLOSE, 0 ,0L);
  1065.                      CurrentCycle = 0; // Make sure don't send message twice if system is slow.
  1066.                  }
  1067.              }
  1068.              return TRUE;
  1069.  
  1070.         case WM_COMMAND:
  1071.              switch (lParam)
  1072.              {
  1073.                 // Get user password...
  1074.                 case testPW:
  1075.                      static FARPROC fpfnGetUserPDialog;
  1076.                      BOOL test;
  1077.  
  1078.                      ShowCursor (TRUE);
  1079.                      fpfnGetUserPDialog = MakeProcInstance ((FARPROC)GetUserPDialog, HInst);
  1080.                      test = DialogBox (HInst, MAKEINTRESOURCE(IDD_GETUSERPASSWORD), hWnd, (DLGPROC) fpfnGetUserPDialog);
  1081.                      FreeProcInstance (fpfnGetUserPDialog);
  1082.                      ShowCursor (FALSE);
  1083.                      if (test == 0)
  1084.                      {
  1085.                         // reset mouse pointer and return back to screen saver
  1086.                         GetCursorPos(&lastMPos);
  1087.                         SetActiveWindow (hWnd);
  1088.                      }
  1089.                      else
  1090.                          PostMessage (hWnd, WM_CLOSE, 0, 0L );
  1091.                      semiphore--;      // Free up semiphore.
  1092.                      return TRUE;
  1093.              }
  1094.              break;
  1095.  
  1096.         case WM_MOUSEMOVE:
  1097.              if ((LOWORD(lParam) == lastMPos.x) &&
  1098.                  (HIWORD(lParam) == lastMPos.y))
  1099.             {
  1100.                     break;
  1101.             }
  1102.  
  1103.         case WM_KEYDOWN:
  1104.         case WM_SYSKEYDOWN:
  1105.         case WM_LBUTTONDOWN:
  1106.         case WM_MBUTTONDOWN:
  1107.         case WM_RBUTTONDOWN:
  1108.              // Implement password check!
  1109.              if (semiphore == 0)
  1110.              {
  1111.                 if ((UsePassword != 0) && (strcmp (Password, "~") != 0))
  1112.                 {
  1113.                     semiphore++;    // Implement locking action.
  1114.                     PostMessage (hWnd, WM_COMMAND, 0, testPW);
  1115.                     break;
  1116.                 }
  1117.                 PostMessage (hWnd, WM_CLOSE, 0, 0L );
  1118.              }
  1119.              break;
  1120.  
  1121.  
  1122.         case WM_CLOSE:
  1123.         case WM_DESTROY:
  1124.              // delete pMyBall, pZDist;
  1125.              ShowCursor (TRUE);
  1126.              PostQuitMessage (0);
  1127.              return 0;
  1128.     }
  1129.     
  1130.     return DefWindowProc (hWnd, message, wParam, lParam);
  1131. }
  1132.